package org.lemon.transport.context.service.request;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.ByteString;
import lombok.extern.slf4j.Slf4j;
import org.lemon.transport.context.service.queue.QueueRequestTemplate;
import org.lemon.transport.context.data.queue.message.ProtoQueueMessage;
import org.lemon.transport.context.service.queue.provider.RabbitMqTransportQueueFactory;
import org.lemon.transport.context.service.queue.stats.MessagesStats;
import org.lemon.transport.context.service.queue.stats.StatsFactory;
import org.lemon.transport.context.service.queue.stats.StatsType;
import org.server.transport.gen.SessionProto;
import org.springframework.stereotype.Component;

import java.util.UUID;

@Slf4j
@Component
public class DeviceAuthRequestTemplate {

    protected MessagesStats deviceTokenValidateStats;
    protected MessagesStats basicMqttCredTokenValidateStats;
    protected MessagesStats deviceX509CertValidateStats;

    private final QueueRequestTemplate<ProtoQueueMessage<SessionProto.ValidateDeviceTokenRequestMsg>,
            ProtoQueueMessage<SessionProto.ValidateDeviceCredentialsResponseMsg>> tokenAuthRequestTemplate;

    private final QueueRequestTemplate<ProtoQueueMessage<SessionProto.ValidateDeviceX509CertRequestMsg>,
            ProtoQueueMessage<SessionProto.ValidateDeviceCredentialsResponseMsg>> x509AuthRequestTemplate;

    private final QueueRequestTemplate<ProtoQueueMessage<SessionProto.ValidateBasicMqttCredRequestMsg>,
            ProtoQueueMessage<SessionProto.ValidateDeviceCredentialsResponseMsg>> mqttCredAuthRequestTemplate;

    public DeviceAuthRequestTemplate(RabbitMqTransportQueueFactory queueFactory, StatsFactory statsFactory) {
        this.deviceTokenValidateStats = statsFactory.createMessagesStats(StatsType.DEVICE_TOKEN_AUTH + ".producer");
        this.basicMqttCredTokenValidateStats = statsFactory.createMessagesStats(StatsType.BASIC_MQTT_CRED_AUTH + ".producer");
        this.deviceX509CertValidateStats = statsFactory.createMessagesStats(StatsType.DEVICE_X509_CERT_AUTH + ".producer");
        this.tokenAuthRequestTemplate = queueFactory.createTokenAuthRequestTemplate();
        this.x509AuthRequestTemplate = queueFactory.createX509AuthRequestTemplate();
        this.mqttCredAuthRequestTemplate = queueFactory.createMqttCredAuthRequestTemplate();
        tokenAuthRequestTemplate.setMessagesStats(deviceTokenValidateStats);
        x509AuthRequestTemplate.setMessagesStats(deviceX509CertValidateStats);
        mqttCredAuthRequestTemplate.setMessagesStats(basicMqttCredTokenValidateStats);
    }

    public SessionProto.ValidateDeviceCredentialsResponseMsg deviceTokenValidate(SessionProto.ValidateDeviceTokenRequestMsg request) {
        log.debug("api: deviceTokenValidate {}", request.toString());
        ProtoQueueMessage<SessionProto.ValidateDeviceTokenRequestMsg> requestMsg = new ProtoQueueMessage<>(UUID.randomUUID(), request);
        ListenableFuture<ProtoQueueMessage<SessionProto.ValidateDeviceCredentialsResponseMsg>> future = tokenAuthRequestTemplate.send(requestMsg);
        return processResponseFuture(future);
    }

    public SessionProto.ValidateDeviceCredentialsResponseMsg basicMqttCredTokenValidate(SessionProto.ValidateBasicMqttCredRequestMsg request) {
        log.debug("api: basicMqttCredTokenValidate {}", request.toBuilder());
        ProtoQueueMessage<SessionProto.ValidateBasicMqttCredRequestMsg> requestMsg = new ProtoQueueMessage<>(UUID.randomUUID(), request);
        ListenableFuture<ProtoQueueMessage<SessionProto.ValidateDeviceCredentialsResponseMsg>> future = mqttCredAuthRequestTemplate.send(requestMsg);
        //return processResponseFuture(future);
        return getDeviceCredentialsValidateResponseMsg(request.getClientId(), Long.parseLong(request.getPassword()));
    }

    public SessionProto.ValidateDeviceCredentialsResponseMsg deviceX509CertValidate(SessionProto.ValidateDeviceX509CertRequestMsg request) {
        log.debug("api: deviceX509CertValidate {}", request.toString());
        ProtoQueueMessage<SessionProto.ValidateDeviceX509CertRequestMsg> requestMsg = new ProtoQueueMessage<>(UUID.randomUUID(), request);
        ListenableFuture<ProtoQueueMessage<SessionProto.ValidateDeviceCredentialsResponseMsg>> future = x509AuthRequestTemplate.send(requestMsg);
        return processResponseFuture(future);
    }

    private SessionProto.ValidateDeviceCredentialsResponseMsg processResponseFuture(ListenableFuture<ProtoQueueMessage<SessionProto.ValidateDeviceCredentialsResponseMsg>> future) {
//        try {
//            return future.get().getValue();
//        } catch (InterruptedException | ExecutionException e) {
//            log.error("deviceTokenValidate error", e);
//            throw new RuntimeException("deviceTokenValidate error", e);
//        }
        return getDeviceCredentialsValidateResponseMsg("设备1", 1001L);
    }

    private SessionProto.ValidateDeviceCredentialsResponseMsg getDeviceCredentialsValidateResponseMsg(String deviceName, Long deviceId) {

        if(deviceName.equals("gateway_device")){
            return gatewayDevice(deviceName);
        }
        return device(deviceName, deviceId);
    }

    private SessionProto.ValidateDeviceCredentialsResponseMsg device(String deviceName, Long deviceId){

        SessionProto.ValidateDeviceCredentialsResponseMsg.Builder builder = SessionProto.ValidateDeviceCredentialsResponseMsg.newBuilder();
        SessionProto.DeviceInfoProto.Builder deviceInfoBuilder = SessionProto.DeviceInfoProto.newBuilder();
        deviceInfoBuilder.setTenantId(1L);
        deviceInfoBuilder.setProjectId(1L);
        deviceInfoBuilder.setDeviceId(1001L);
        deviceInfoBuilder.setDeviceName(deviceName);
        deviceInfoBuilder.setAdditionalInfo("");
        deviceInfoBuilder.setDeviceProfileId(1L);
        deviceInfoBuilder.setDeviceType("TEST");
        deviceInfoBuilder.setPowerMode("PSM");
        builder.setDeviceInfo(deviceInfoBuilder.build());

        builder.setCredentialsBody("SYDJJXZALIJDKUD=");
        ByteString bytes = ByteString.copyFromUtf8("nihao");
        builder.setProfileBody(bytes);

        return builder.build();
    }

    private SessionProto.ValidateDeviceCredentialsResponseMsg gatewayDevice(String deviceName){

        SessionProto.ValidateDeviceCredentialsResponseMsg.Builder builder = SessionProto.ValidateDeviceCredentialsResponseMsg.newBuilder();
        SessionProto.DeviceInfoProto.Builder deviceInfoBuilder = SessionProto.DeviceInfoProto.newBuilder();
        deviceInfoBuilder.setTenantId(1L);
        deviceInfoBuilder.setProjectId(1L);
        deviceInfoBuilder.setDeviceId(1002L);
        deviceInfoBuilder.setDeviceName(deviceName);
        String additionalInfo = "{\"gateway\":true,\"overwriteActivityTime\":true,\"lastConnectedGateway\":null}";
        deviceInfoBuilder.setAdditionalInfo(additionalInfo);
        deviceInfoBuilder.setDeviceProfileId(1L);
        deviceInfoBuilder.setDeviceType("TEST");
        deviceInfoBuilder.setPowerMode("PSM");
        builder.setDeviceInfo(deviceInfoBuilder.build());

        builder.setCredentialsBody("SYDJJXZALIJDKUD=");
        ByteString bytes = ByteString.copyFromUtf8("nihao");
        builder.setProfileBody(bytes);

        return builder.build();
    }
}
